﻿// This software is the confidential and proprietary information of NetBay.
// Such confidential information should not be disclosed.
// NetBay copyright(c) 2012

#region Using
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Security;
using NetBay.Core.BusinessEntities;
using NetBay.Core.Encryption.Licensing;
using Rio.Applications.Web.Services;
using System.Management;
#endregion

namespace Rio.Applications.Web.LicenseFiles
{
    public class LicenseAuthorization: LicenseAuthorizationBase
    {
        /// <summary>
        /// validates the license and if the app should run; if the license is valid the
        /// method will complete, if not it will throw a security exception.
        /// </summary>
        /// <param name="licenseFile">The license file.</param>
        /// <returns></returns>
        /// <exception cref="SecurityException">thrown if the license is invalid or expired</exception>
        public override LicenseTerms ValidateLicense(string licenseFile)
        {
            LicenseFile license = LicenseFile.Load(licenseFile);
            if ( license == null )
            {
                throw new SecurityException("Invalid license file");
            }

            // get the valid terms for the license: (this checks the digital signature on the license file)
            LicenseTerms terms = GetValidTerms(license, license.PublicKey);
            
            // ensure a valid license-terms object was returned:
            if ( terms != null )
            {
                var businessEntitiesDomainService = new BusinessEntitiesDomainService();

                #region Reseller Key and Product Name check
                if (terms.ProductName.Equals(string.Empty) 
                    || terms.ResellerKey.Equals(string.Empty) 
                    )
                {
                    System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                            "Product name or Resseller key not valid.");
                    throw new SecurityException("Invalid License File ! Product name or Resseller key not present. ");
                }
                #endregion

                #region Date check
                // validate the date-range of the license terms:
                if ( DateTime.Now.CompareTo(terms.EndDate) <= 0 )
                {
                    if ( DateTime.Now.CompareTo(terms.StartDate) < 0 )
                    {
                        System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                            "The license is not valid anymore.");

                        // license terms not valid yet.
                        throw new SecurityException("Invalid License File ! License Terms Not Valid Until: " + terms.StartDate.ToShortDateString());
                    }
                }
                else
                {
                    // license terms have expired.
                    System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license is not valid anymore.");
                    throw new SecurityException("Invalid License File ! License Terms Expired On: " + terms.EndDate.ToShortDateString());
                }
                #endregion

                #region Number of users check
                if ( !terms.NbUserDeclaredAllowed.Equals(0) )
                {
                    IEnumerable<ReturnLong> getNbUserDeclared = businessEntitiesDomainService.GetNbUserDeclared();
                    if (((List<ReturnLong>)getNbUserDeclared).Count > 0)
                    {
                        long nbUserDeclared = ((List<ReturnLong>) getNbUserDeclared)[0].Value;
                        if ( nbUserDeclared > terms.NbUserDeclaredAllowed )
                        {
                            System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license you bought allows only " + terms.NbUserDeclaredAllowed + " users.");
                            throw new SecurityException("Invalid License File ! Number of users allowed exceeded.");
                        }
                    }
                }
                    

                #endregion

                #region Number of documents check
                if ( !terms.NbDocumentsAllowed.Equals(0) )
                {
                    IEnumerable<ReturnLong> getNbDocument = businessEntitiesDomainService.GetNbDocument();
                    if ( ((List<ReturnLong>)getNbDocument).Count > 0 )
                    {
                        long nbDocument = ((List<ReturnLong>)getNbDocument)[0].Value;
                        if ( nbDocument > terms.NbDocumentsAllowed )
                        {
                            System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                          "The license you bought allows only " + terms.NbDocumentsAllowed + " documents.");
                            throw new SecurityException("Invalid License File ! Number of documents allowed exceeded.");
                        }
                    }
                }
                #endregion

                #region Domain check

                if ( !terms.DomainName.Equals(string.Empty))
                {
                    if (!System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName.Equals(terms.DomainName))
                    {
                        System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                            "The license does not allow you to use RioGed on this domain.");
                        throw new SecurityException("Invalid License File ! RioGed is not well installed.");
                    }
                }
                
                #endregion

                #region Client reference check
                if ( !terms.ClientKey.Equals(string.Empty) )
                {
                    if (!AppDomain.CurrentDomain.BaseDirectory.Contains(terms.ClientKey))
                    {
                        System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                                                                       "The license does not correspond to the client.");
                        throw new SecurityException("Invalid License File ! RioGed licence file does not correspond to sale.");
                    }
                }

                #endregion

                #region Client HDD SerialNumber check // Possible error code 300 or 301
                if ( !terms.HddSerialNumber.Equals(string.Empty) )
                {
                    try
                    {
                        List<string> allHddSerialNumber = new List<string>();
                        String query = "SELECT * FROM Win32_DiskDrive";

                        ManagementObjectSearcher mosHddSerialNumber = new ManagementObjectSearcher(query);

                        ManagementObjectCollection mocHddSerialNumber = mosHddSerialNumber.Get();

                        foreach ( ManagementObject item in mocHddSerialNumber )
                        {
                            allHddSerialNumber.Add(Convert.ToString(item["SerialNumber"]));
                        }

                        if (!allHddSerialNumber.Contains(terms.HddSerialNumber))
                        {
                            System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license has raise an error code 301.");
                            throw new SecurityException("Invalid License File ! RioGed cannot be used. Error code 301.");
                        }
                    }
                    catch(Exception ex)
                    {
                        NetBay.Core.Log.LogManager.Instance().LogDebug("Licence Check error CODE 300 : [" + ex.InnerException + "]");
                        System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license has raise an error code 300.");
                        throw new SecurityException("Invalid License File ! RioGed cannot be used. Error code 300.");
                    }
                    
                }
                #endregion

                #region Client HDD Signature check // Possible error code 400 or 401
                if ( !terms.HddSignature.Equals(string.Empty) )
                {
                    try
                    {
                        List<string> allHddSignature = new List<string>();
                        String query = "SELECT * FROM Win32_DiskDrive";

                        ManagementObjectSearcher mosHddSignature = new ManagementObjectSearcher(query);

                        ManagementObjectCollection mocHddSignature = mosHddSignature.Get();

                        foreach ( ManagementObject item in mocHddSignature )
                        {
                            allHddSignature.Add(Convert.ToString(item["Signature"]));
                        }

                        if ( !allHddSignature.Contains(terms.HddSignature) )
                        {
                            System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license has raise an error code 401.");
                            throw new SecurityException("Invalid License File ! RioGed cannot be used. Error code 401.");
                        }
                    }
                    catch ( Exception ex )
                    {
                        NetBay.Core.Log.LogManager.Instance().LogDebug("Licence Check error CODE 400 : [" + ex.InnerException + "]");
                        System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license has raise an error code 400.");
                        throw new SecurityException("Invalid License File ! RioGed cannot be used. Error code 400.");
                    }
                    
                }
                #endregion

                #region Mac Adress check and Ip Adress check // Possible error code 500 or 501 or 601
                if ( !terms.MacAdress.Equals(string.Empty) && !terms.IpAdress.Equals(string.Empty) )
                {
                    try
                    {
                        List<string> macAdress = new List<string>();
                        List<string> ipAdress = new List<string>();
                        foreach ( NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces() )
                        {
                            if ( nic.OperationalStatus == OperationalStatus.Up )
                            {
                                if ( !Convert.ToString(nic.GetPhysicalAddress().ToString()).Equals(string.Empty) )
                                {
                                    macAdress.Add(Convert.ToString(nic.GetPhysicalAddress().ToString()));
                                }

                                if ( !Convert.ToString(nic.GetIPProperties().UnicastAddresses[0].Address.ToString()).Equals(string.Empty) )
                                {
                                    ipAdress.Add(Convert.ToString(nic.GetIPProperties().UnicastAddresses[0].Address.ToString()));
                                }
                            }
                        }

                        if ( !macAdress.Contains(terms.MacAdress) )
                        {
                            System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license has raise an error code 501.");
                            throw new SecurityException("Invalid License File ! RioGed cannot be used. Error code 501.");
                        }


                        if ( !ipAdress.Contains(terms.IpAdress) )
                        {
                            System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license has raise an error code 601.");
                            throw new SecurityException("Invalid License File ! RioGed cannot be used. Error code 601.");
                        }

                    }
                    catch ( Exception ex )
                    {
                        NetBay.Core.Log.LogManager.Instance().LogDebug("Licence Check error CODE 500 : [" + ex.InnerException + "]");
                        System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license has raise an error code 500.");
                        throw new SecurityException("Invalid License File ! RioGed cannot be used. Error code 500.");
                    }
                }

                #endregion

                #region Processor Id check // Possible error code 700 or 701
                if ( !terms.ProcessorId.Equals(string.Empty) )
                {
                    try
                    {
                        List<string> allProcessorId = new List<string>();
                        string cpuInfo = String.Empty;
                        ManagementClass mc = new ManagementClass("Win32_Processor");
                        ManagementObjectCollection moc2 = mc.GetInstances();
                        foreach ( ManagementObject mo in moc2 )
                        {
                            if ( cpuInfo == String.Empty )
                            {
                                // only return cpuInfo from first CPU
                                allProcessorId.Add(Convert.ToString(mo.Properties["ProcessorId"].Value.ToString()));
                            }
                        }

                        if ( !allProcessorId.Contains(terms.ProcessorId) )
                        {
                            System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license has raise an error code 701.");
                            throw new SecurityException("Invalid License File ! RioGed cannot be used. Error code 701.");
                        }
                    }
                    catch ( Exception ex )
                    {
                        NetBay.Core.Log.LogManager.Instance().LogDebug("Licence Check error CODE 700 : [" + ex.InnerException + "]");
                        System.Web.HttpContext.Current.Application.Add("LicenseErrorMessage",
                           "The license has raise an error code 700.");
                        throw new SecurityException("Invalid License File ! RioGed cannot be used. Error code 700.");
                    }

                }
                #endregion
            }
            else
            {
                // the license file was not valid.
                throw new SecurityException("Invalid License File!");
            }

            return terms;
        }
    }
}